<?php

namespace app\data\service;

use think\admin\extend\DataExtend;
use think\admin\Service;

/**
 * 快递查询数据服务
 * Class ExpressService
 * @package app\data\service
 */
class ExpressService extends Service
{
    /**
     * 模拟计算快递费用
     * @param array $codes 模板编号
     * @param string $provName 省份名称
     * @param string $cityName 城市名称
     * @param integer $truckCount 邮费基数
     * @return array [邮费金额, 计费基数, 模板编号, 计费描述]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function amount(array $codes, string $provName, string $cityName, int $truckCount = 0): array
    {
        if (empty($codes)) return [0, $truckCount, '', '邮费模板编码为空！'];
        $map = [['status', '=', 1], ['deleted', '=', 0], ['code', 'in', $codes]];
        $template = $this->app->db->name('BasePostageTemplate')->where($map)->order('sort desc,id desc')->find();
        if (empty($template)) return [0, $truckCount, '', '邮费模板编码无效！'];
        $rule = json_decode($template['normal'] ?: '[]', true) ?: [];
        foreach (json_decode($template['content'] ?: '[]', true) ?: [] as $item) {
            if (isset($item['city']) && is_array($item['city'])) foreach ($item['city'] as $city) {
                if ($city['name'] === $provName && in_array($cityName, $city['subs'])) {
                    $rule = $item['rule'];
                    break 2;
                }
            }
        }
        [$firstNumber, $firstAmount] = [$rule['firstNumber'] ?: 0, $rule['firstAmount'] ?: 0];
        [$repeatNumber, $repeatAmount] = [$rule['repeatNumber'] ?: 0, $rule['repeatAmount'] ?: 0];
        if ($truckCount <= $firstNumber) {
            return [$firstAmount, $truckCount, $template['code'], "首件计费，不超过{$firstNumber}件"];
        } else {
            $amount = $repeatNumber > 0 ? $repeatAmount * ceil(($truckCount - $firstNumber) / $repeatNumber) : 0;
            return [$firstAmount + $amount, $truckCount, $template['code'], "续件计费，超出{$firstNumber}件续件{$amount}元"];
        }
    }


    /**
     * 获取快递模板数据
     * @return array
     */
    public function templates(): array
    {
        $map = ['status' => 1, 'deleted' => 0];
        $query = $this->app->db->name('BasePostageTemplate')->where($map);
        return $query->order('sort desc,id desc')->column('code,name,normal,content', 'code');
    }

    /**
     * 配送区域树型数据
     * @param integer $level 最大等级
     * @param null|integer $status 状态筛选
     * @return array
     */
    public function region(int $level = 3, ?int $status = null): array
    {
        $query = $this->app->db->name('BasePostageRegion');
        if (is_numeric($level)) $query->where('level', '<=', $level);
        if (is_numeric($status)) $query->where(['status' => $status]);
        $items = DataExtend::arr2tree($query->column('id,pid,name,status', 'id'), 'id', 'pid', 'subs');
        // 排序子集为空的省份和城市
        foreach ($items as $ik => $item) {
            foreach ($item['subs'] as $ck => $city) {
                if (isset($city['subs']) && empty($city['subs'])) unset($items[$ik]['subs'][$ck]);
            }
            if (isset($item['subs']) && empty($item['subs'])) unset($items[$ik]);
        }
        return $items;
    }


    /**
     * 检查是否被占用了省市
     * @param $cityDockingConfigId
     * @param $data
     * @return string
     */
    public function checkCanUpdate($cityDockingConfigId, $data): string
    {
        $query = $this->app->db->name('BasePostageRegion')->where('status', 1)->field('id,pid,name,level,uuid_docking,city_docking_config_id');
        $tree = DataExtend::arr2tree($query->column('id,pid,name,city_docking_config_id', 'id'), 'id', 'pid', 'subs');
        $province2IdMap = ExpressService::instance()->getProvince2IdMap();

        foreach ($tree as $province) {
            foreach ($province['subs'] ?? [] as $city) {
                if (!empty($city['city_docking_config_id'])) {
                    $mapKey = $province2IdMap[$province['name']] . '-' . $city['name'];
                    $map[$mapKey] = $city['city_docking_config_id'];
                }
            }
        }

        $wheres = $this->formatWhere($data);

        foreach ($wheres as $where) {
            foreach ($where['name'] ?? [] as $name) {
                $key = $where['pid'] . '-' . $name;
                if (isset($map[$key]) && $map[$key] != $cityDockingConfigId) {
                    return "{$name}已经分配过了";
                }
            }
        }

        return '';
    }

    /**
     * 格式化条件
     * @param $data
     * @return array
     */
    public function formatWhere($data)
    {
        $province2IdMap = ExpressService::instance()->getProvince2IdMap();

        $content = json_decode($data['content'] ?? [], true);
        foreach ($content[0] ?? [] as $item) {
            foreach ($item as $province) {
                if (!empty($province2IdMap[$province['name']])) {
                    $where = [
                        'pid' => $province2IdMap[$province['name']],
                        'name' => $province['subs'] ?? [],
                    ];
                    $wheres[] = $where;
                }
            }
        }

        return $wheres ?? [];
    }

    /**
     * 格式化城市
     * @param $data
     * @return array
     */
    public function formatCity(&$data)
    {
        foreach ($data as &$item) {
            if (is_string($item['content'])) {
                $item['content'] = json_decode($item['content'], true);

                $item['city_text'] = [];
                foreach ($item['content'][0] ?? [] as $province) {
                    foreach ($province as $city) {
                        $item['city_text'] = array_merge($city['subs'], $item['city_text']);
                    }
                }
                if (!empty($item['city_text'])) {
                    $item['city_text'] = implode(' | ', $item['city_text']);
                }
            }
        }
    }

    /**
     * 省份映射为ID
     * @return array
     */
    public function getProvince2IdMap(): array
    {
        return $this->app->db->name('BasePostageRegion')->where('level', 1)->where('status', 1)->column('id', 'name');
    }

    /**
     * 保存配置
     * @param $id
     * @param $wheres
     * @param $uuidDocking
     * @return void
     * @throws \think\db\exception\DbException
     */
    public function updateBasePostageRegionConfig($id, $wheres, $uuidDocking)
    {
        $this->app->db->name('BasePostageRegion')->where('city_docking_config_id', $id)->update(['city_docking_config_id' => 0]);
        foreach ($wheres as $where) {
            $this->app->db->name('BasePostageRegion')->where('pid', $where['pid'])->whereIn('name', $where['name'])->update([
                'city_docking_config_id' => $id,
                'uuid_docking' => $uuidDocking,
            ]);
        }
    }
}